package com.gitee.wsl.common.chart.render.background.axis.line

import android.graphics.Canvas
import com.gitee.wsl.common.chart.ChartEnum
import com.gitee.wsl.common.chart.render.background.axis.model.PlotAxisTick
import com.gitee.wsl.math.Math
import com.gitee.wsl.jvm.math.sub
import com.gitee.wsl.mathematics.geometry.shape.Rectangle

import kotlin.math.ceil

/**
 * @ClassName DataLineAxis
 * @Description 数据轴(Data Axis)绘制类，负责具体的绘制
 * @author XiongChuanLiang<br/>(xcl_168@aliyun.com)
 *
 */

class DataLineAxis: BaseLineAxis() {

    //轴数据来源
    var axisMin = 0.0f
    var axisMax = 0.0f

    var detailModeSteps = 0.0f

    //是否显示第一个序号的标签文本
    var isShowFirstTick = true

    var dataAxisStd = 0.0f


    /**
     * 返回是否启用明细模式
     * @return 是否有启用
     */
    val isDetailMode: Boolean 
       get() = detailModeSteps.compareTo(0.0f) != 0
    
    /**
     * 返回当前正负标准值，如没设则默认为轴的最小值
     * @return 标准值
     */
    fun getAxisStd(): Float {
        return if (isAxisStdStatus) {
            dataAxisStd
        } else {
            axisMin
        }
    }


    //当前刻度线ID
    var currentId = 0

    /**
     * 返回轴值的范围(即最大-最小值).
     * @return 轴值范围
     */
    val axisRange: Float 
       get(){
        return  Math.sub(axisMax, axisMin)
    }


    /**
     * 数据轴值范围(最大与最小之间的范围)  /  传的的步长  = 显示的Tick总数
     * @return 显示的刻度标记总数
     */
    val axisTickCount: Int 
       get() = ceil(axisRange / axisSteps).toInt()


    /**
     * 依据当前id序号与steps的比较来区分当前是否为主tick
     * @return 是否为主tick
     */
    fun isPrimaryTick(id: Int = currentId): Boolean {
        if (isDetailMode) {
            if (0 == id && isAxisLineVisible) return true
            if (id < detailModeSteps || id % detailModeSteps != 0.0f) return false
        }
        return true
    }

    /**
     * 用于处理明细横式下，细分部份的轴刻度线长度缩短为正常的一半，用来突出主明细刻度
     * @return 刻度线长度
     */
    override var tickMarksLength: Float = 0.0f
        get() {
         return if (isPrimaryTick()) field else field / 2
        }


    override fun renderClipAxisClosed(
        canvas: Canvas,
        plotArea: Rectangle,
        axisLocation: ChartEnum.AxisLocation
    ) {
        val plotLeft: Float = plotArea.left
        val plotTop: Float = plotArea.top
        val plotRight: Float = plotArea.right
        val plotBottom: Float = plotArea.bottom
        when (axisLocation) {
            ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER -> {
                drawAxisLine(canvas, plotLeft, plotTop, plotLeft, plotBottom)
                drawAxisLine(canvas, plotRight, plotTop, plotRight, plotBottom)
            }

            ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER -> {
                drawAxisLine(canvas, plotLeft, plotTop, plotRight, plotTop)
                drawAxisLine(canvas, plotLeft, plotBottom, plotRight, plotBottom)
            }
        }
    }

    override fun renderAxisLabels(
        canvas: Canvas,
        plotArea: Rectangle,
        lstLabels: MutableList<PlotAxisTick>,
        left:Float,
        moveX: Float,
        moveY: Float,
        axisLocation: ChartEnum.AxisLocation
    ) {
        for (i in lstLabels.indices) {
            val t = lstLabels[i]
            val oe = if (i % 2 != 0) ChartEnum.ODD_EVEN.ODD else ChartEnum.ODD_EVEN.EVEN

            currentId = t.id

            when (axisLocation) {
                ChartEnum.AxisLocation.LEFT, ChartEnum.AxisLocation.RIGHT, ChartEnum.AxisLocation.VERTICAL_CENTER ->
                    drawHorizontalTick(left, plotArea.left, canvas, t.x, t.y, t.label, t.x, t.y ,isDrawYAxisTickMarks(plotArea,t.y, moveY))

                ChartEnum.AxisLocation.TOP, ChartEnum.AxisLocation.BOTTOM, ChartEnum.AxisLocation.HORIZONTAL_CENTER ->
                    drawVerticalTick(canvas, t.x, t.y, t.label,  t.x, t.y,isDrawXAxisTickMarks(plotArea,t.x, moveX), oe)
            }
        }
        lstLabels.clear()
    }
}